package reflection;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

/**
 * 反射工具类.
 *
 * @author guanweichen
 * @version 2010-3-4,上午10:29:16
 */
public class ReflectionUtil {

	/**
	 * 根据类名和属性名,拿到属性的get方法.
	 * 
	 * @param propName
	 * @param clazz
	 * @return Method
	 * @throws IntrospectionException
	 */
	public static Method getReadMethod(String propName, Class clazz) {
		PropertyDescriptor[] descriptors;
		try {
			descriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
			for (PropertyDescriptor propertyDescriptor : descriptors) {
				if (propertyDescriptor.getName().equals(propName)) {
					return propertyDescriptor.getReadMethod();
				}
			}
		} catch (IntrospectionException e) {
			throw new RuntimeException("反射异常,没能拿到属性Read方法", e);
		}
		return null;
	}

	/**
	 * 根据类名和属性名,拿到属性的set方法.
	 * 
	 * @param propName
	 * @param clazz
	 * @return Method
	 * @throws IntrospectionException
	 */
	public static Method getWriteMethod(String propName, Class clazz) {
		PropertyDescriptor[] descriptors;
		try {
			descriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
			for (PropertyDescriptor propertyDescriptor : descriptors) {
				if (propertyDescriptor.getName().equals(propName)) {
					return propertyDescriptor.getWriteMethod();
				}
			}
		} catch (IntrospectionException e) {
			throw new RuntimeException("反射异常,没能拿到属性write方法", e);
		}
		return null;
	}

	/**
	 * 得到所有属性的   map<name,type> .
	 * 
	 * @param clazz
	 * @return Map
	 */
	public static Map<String, Class> getAllProperties(Class clazz) {
		Map<String, Class> propMap = new HashMap<String, Class>();
		try {
			PropertyDescriptor[] descriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
			for (PropertyDescriptor propertyDescriptor : descriptors) {
				if (!propertyDescriptor.getName().equals("class"))
					propMap.put(propertyDescriptor.getName(), propertyDescriptor.getPropertyType());
			}
		} catch (IntrospectionException e) {
			throw new RuntimeException("反射异常,没能拿到所有的属性", e);
		}
		return propMap;
	}

	/**
	 * 得到字段的泛型类型,但是必须是public 字段.
	 * 
	 * Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments();
	 * 得到类泛型类型.
	 * 
	 * @param filedName
	 * @param clazz
	 * @return java.lang.reflect.Type[]
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	public static Type[] getGenericsTypes(String filedName, Class clazz) throws SecurityException, NoSuchFieldException {
		ParameterizedType pt = (ParameterizedType) clazz.getField(filedName).getGenericType();
		return pt.getActualTypeArguments();
	}
	
	/**
	 * 得到传入的泛型类型. 如curdDao <T> , modelDao extends class<T> implements interface<T>,返回class的<T>
	 *
	 * @param clazz
	 * @return
	 */
	public static Class getGenericTypeClass(Class clazz) {
		
		Type type = clazz.getGenericSuperclass();
		Type[] params=((ParameterizedType)type).getActualTypeArguments();
		return (Class)params[0];
	}
	
	/**
	 * 得到传入的泛型类型. 如curdDao <T> , modelDao extends class<T> implements interface<T>,返回interface的<T>
	 *
	 * @param clazz
	 * @return
	 */
	public static Class getGenericTypeInterface(Class clazz) {
		
		Type[] types = clazz.getGenericInterfaces();
		if (null == types || types.length == 0) {
			throw new RuntimeException( "读取对象的接口泛型时异常,请检查是否jdk支持泛型,或者对象并没有接口或者接口没有泛型" );
		}
		Type[] params = ((ParameterizedType)types[0]).getActualTypeArguments();
		return (Class)params[0];
	}

}
